package com.gitee.wsl.doc.prosemirror.state.command.mark

import com.gitee.wsl.doc.prosemirror.model.attr.Attrs
import com.gitee.wsl.doc.prosemirror.model.mark.MarkType
import com.gitee.wsl.doc.prosemirror.model.node.ext.getMarkLocation
import com.gitee.wsl.doc.prosemirror.state.Command
import com.gitee.wsl.doc.prosemirror.state.CommandDispatch
import com.gitee.wsl.doc.prosemirror.state.EditorState
import com.gitee.wsl.doc.prosemirror.transform.ext.addMark
import com.gitee.wsl.doc.prosemirror.transform.ext.removeMark

class UpdateMark(
    val markType: MarkType,
    val markAttrs: Attrs
): Command {
    override fun exec(
        state: EditorState,
        dispatch: CommandDispatch?,
    ): Boolean {
        val tr = state.tr
        val doc = tr.doc

        val markLocation = if (!state.selection.isEmpty) {
            state.selection.posRange
        } else if (state.selection._anchor != null) {
            doc.getMarkLocation(state.selection.anchor, markType)
        } else {
            null
        }

        if (markLocation == null) {
            return false
        }

        if (state.selection.isEmpty) {
            if (doc.rangeHasMark(markLocation.first, markLocation.second, markType)) {
                tr.removeMark(markLocation.first, markLocation.second, markType)
            } else {
                return false
            }
        }

        val markItem = markType.create(markAttrs)
        dispatch?.apply(tr.addMark(markLocation.first, markLocation.second, markItem))
        return true
    }
}

fun Command.Companion.updateMark(
    markType: MarkType,
    markAttrs: Attrs
) = UpdateMark(markType, markAttrs)